using System;
using System.Collections.Generic;
using Codice.Client.Common.GameUI;
using Project.ViewModels;
using Project.Views.Abstractions;
using UnityEngine;
using UnityEngine.UI;

namespace Project.Views
{
    public class InventoryUIView : MonoUIViewBase<InventoryViewModel>, IDisposable
    {
        private List<SlotUIView> _slotViews;

        [SerializeField] private Button _resetButton;
        [SerializeField] private Button _idButton;
        [SerializeField] private Button _quantityButton;
        [SerializeField] private Button _nameButton;
        [SerializeField] private Button _groupButton;
        [Space]
        [SerializeField] private Button _addItemsButton;
        [SerializeField] private Button _addButton;
        [SerializeField] private Button _removeButton;
        [Space]
        [SerializeField] private Transform _slotsContainer;
        [SerializeField] private GameObject _slotPrefab;

        public void Dispose()
        {
            ViewModel.SlotViewModels.ElementAdded -= OnSlotViewModelsElementAdded;
            ViewModel.SlotViewModels.ElementRemoved -= OnSlotViewModelsElementRemoved;
            ViewModel.CanAddSlotToEnd.ValueChanged -= OnCanAddSlotToEndValueChanged;
            ViewModel.CanRemoveSlotFromEnd.ValueChanged -= OnCanRemoveSlotFromEndValueChanged;
            ViewModel.IsEmpty.ValueChanged -= OnIsEmptyValueChanged;

            _resetButton.onClick.RemoveListener(ViewModel.Reset);
            _idButton.onClick.RemoveListener(ViewModel.OrderItemsByItemId);
            _quantityButton.onClick.RemoveListener(ViewModel.OrderItemsByQuantityOfItems);
            _nameButton.onClick.RemoveListener(ViewModel.OrderItemsByItemName);
            _groupButton.onClick.RemoveListener(ViewModel.GroupItems);
            _addItemsButton.onClick.RemoveListener(ViewModel.AddRandomItemsToRandomSlot);
            _addButton.onClick.RemoveListener(ViewModel.AddSlotToEnd);
            _removeButton.onClick.RemoveListener(ViewModel.RemoveSlotFromEnd);
        }

        protected override void OnAfterInitialization()
        {
            for (int i = _slotsContainer.childCount - 1; i >= 0; i--)
                DestroyImmediate(_slotsContainer.GetChild(i).gameObject);

            _slotViews = new List<SlotUIView>();

            for (int i = 0, length = ViewModel.SlotViewModels.Count; i < length; i++)
                OnSlotViewModelsElementAdded(i, ViewModel.SlotViewModels[i]);

            OnCanAddSlotToEndValueChanged(ViewModel.CanAddSlotToEnd.Value);
            OnCanRemoveSlotFromEndValueChanged(ViewModel.CanRemoveSlotFromEnd.Value);
            OnIsEmptyValueChanged(ViewModel.IsEmpty.Value);

            ViewModel.SlotViewModels.ElementAdded += OnSlotViewModelsElementAdded;
            ViewModel.SlotViewModels.ElementRemoved += OnSlotViewModelsElementRemoved;
            ViewModel.CanAddSlotToEnd.ValueChanged += OnCanAddSlotToEndValueChanged;
            ViewModel.CanRemoveSlotFromEnd.ValueChanged += OnCanRemoveSlotFromEndValueChanged;
            ViewModel.IsEmpty.ValueChanged += OnIsEmptyValueChanged;

            _resetButton.onClick.AddListener(ViewModel.Reset);
            _idButton.onClick.AddListener(ViewModel.OrderItemsByItemId);
            _quantityButton.onClick.AddListener(ViewModel.OrderItemsByQuantityOfItems);
            _nameButton.onClick.AddListener(ViewModel.OrderItemsByItemName);
            _groupButton.onClick.AddListener(ViewModel.GroupItems);
            _addItemsButton.onClick.AddListener(ViewModel.AddRandomItemsToRandomSlot);
            _addButton.onClick.AddListener(ViewModel.AddSlotToEnd);
            _removeButton.onClick.AddListener(ViewModel.RemoveSlotFromEnd);
        }

        private void DestroySlot(int index)
        {
            Destroy(_slotViews[index].gameObject);

            _slotViews.RemoveAt(index);
        }

        private void CreateSlot(int index, SlotViewModel slotViewModel)
        {
            var slotObject = Instantiate(_slotPrefab, _slotsContainer);
            var slotView = slotObject.GetComponent<SlotUIView>();

            slotObject.name = $"{_slotPrefab.name}_{index}";
            slotObject.transform.SetSiblingIndex(index);

            _slotViews.Insert(index, slotView);

            slotView.Initialize(slotViewModel, RootUIView);
        }

        private void OnSlotViewModelsElementAdded(int index, SlotViewModel addedElement) => 
            CreateSlot(index, addedElement);
        private void OnSlotViewModelsElementRemoved(int index, SlotViewModel removedElement) => 
            DestroySlot(index);
        private void OnCanAddSlotToEndValueChanged(bool newValue) => 
            _addButton.interactable = newValue;
        private void OnCanRemoveSlotFromEndValueChanged(bool newValue) => 
            _removeButton.interactable = newValue;
        private void OnIsEmptyValueChanged(bool newValue)
        {
            _idButton.interactable = !newValue;
            _quantityButton.interactable = !newValue;
            _nameButton.interactable = !newValue;
            _groupButton.interactable = !newValue;
        }
    }
}
